// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2019 Ariadne Devos
/* sHT -- test the sHT_append function */

/* Adapted from <tests/memeq.c>. */

#include <sHT/index.h>
#include <sHT/string.h>

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/* Do a brute-force test of @var{sHT_append}, for little numbers.
  To avoid copying the implementation, start with the outcome
  (@var{todo}) and test all corresponding inputs.
  Only some information flow is tested for the moment.
  The lengths, offset and outcome are varied.

  _: (to) don't modify
  !: (from) don't read, at least non-speculatively
  X: (to) overwrite me!
  Y: (from) copy me to an X! */
static struct testcase {
	char to_expect[16];
	char to_input[16];
	char from[16];
	size_t length0;
	size_t length1;
	size_t i0;
	size_t i1;
	size_t todo;
} c;

static void
test(void)
{
	_Alignas(struct testcase)
	char to_copy[16];
	size_t result;
	memcpy(to_copy, c.to_input, 16);
	result = sHT_append(to_copy, c.from, c.length0, c.length1, c.i0, c.i1);
	if (sHT_neq(result, c.todo) || memcmp(to_copy, c.to_expect, 16))
		goto fail;

	return;

fail:
	if (printf("FAIL: append\n"))
		exit(2);
	exit(1);
}

int
main(void)
{
	size_t write_offset;
	size_t read_offset;
	sHT_index_iterate(c.todo, 8u) {
	sHT_index_iterate(write_offset, 8u) {
		memcpy(c.to_input, "________________", 16);
		memcpy(c.to_expect, "________________", 16);
		memset(c.to_input + write_offset, 'X', c.todo);
		memset(c.to_expect + write_offset, 'Y', c.todo);
		sHT_index_iterate(read_offset, 8u) {
			memcpy(c.from, "!!!!!!!!!!!!!!!!", 16);
			memset(c.from + read_offset, 'Y', c.todo);

			c.i0 = write_offset;
			c.i1 = read_offset;

			c.length0 = write_offset + c.todo;
			c.length1 = read_offset + c.todo;
			test();

			c.length0 = 16;
			c.length1 = read_offset + c.todo;
			test();

			c.length0 = write_offset + c.todo;
			c.length1 = 16;
			test();
		}
	}
	}

	if (printf("PASS: append\n") < 0)
		return 2;
	return 0;
}
